package com.superc.server;
// VietSpider HTMLParser
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;

@SuppressWarnings("serial")
public class HttpProxyServlet extends HttpServlet {

	private static final Logger log = Logger.getLogger(HttpProxyServlet.class.getName()); 
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		doPost(req,resp);
		
	}
	
	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		//��ȡ�ͻ��˵�������Ϣ
		String urlAddress=base64Decode(req.getParameter("address"));
		String httpHeader=base64Decode(req.getParameter("header"));
		String httpMethod=req.getParameter("method");
		String httpParameter=base64Decode(req.getParameter("parameter"));	
		proxyWebRequest(urlAddress,httpMethod,splitHeader(httpHeader),httpParameter,resp);
		
	}
	
	private ArrayList<KeyValuePair> splitHeader(String httpHeader) {
		if(httpHeader==null) return null;
		String[] heads=httpHeader.split("\r\n");
		ArrayList<KeyValuePair> headerList=new ArrayList<KeyValuePair>();
		for (String head : heads) {
			int keyPos=head.indexOf(": ");
			headerList.add(new KeyValuePair(head.substring(0, keyPos),head.substring(keyPos+2)));
		}
		return headerList;
	}

	private String base64Decode(String data){
		if(data==null) return null;
		try {
			return new String(Base64.decode(data));
		} catch (IOException e) {
			return null;
		}
		 
	}
	
	private boolean proxyWebRequest(String url, String method,ArrayList<KeyValuePair> headers, String postData, HttpServletResponse resp)
			throws IllegalArgumentException {
		URLFetchService service=URLFetchServiceFactory.getURLFetchService();
		try {
			HTTPRequest request=new HTTPRequest(new URL(url),HTTPMethod.valueOf(method));
			if(headers!=null){
				for (KeyValuePair keyValuePair : headers) {
					request.addHeader(new HTTPHeader(keyValuePair.key, keyValuePair.value));
				}
				request.addHeader(new HTTPHeader("Accept-Encoding", "identity, *;q=0"));
				request.addHeader(new HTTPHeader("Connection", "close"));
			}
			if (postData != null && postData.length() > 0) {
				request.setPayload(postData.getBytes());
			}
			//request.getFetchOptions().doNotFollowRedirects();
			HTTPResponse response=service.fetch(request);
			if(response.getResponseCode() == HttpURLConnection.HTTP_OK) {
				try {
					for (HTTPHeader header : response.getHeaders()) {
						System.out.println(header.getName()+ ":" + header.getValue());
						if(!header.getName().equalsIgnoreCase("transfer-encoding") &&
								!header.getName().equalsIgnoreCase("content-length")){
							if(header.getName().equalsIgnoreCase("Set-Cookie")){
								resp.addHeader(header.getName(), header.getValue()
										.replace("domain=","domain=."));
							}
							else{
								resp.addHeader(header.getName(),header.getValue());
							}
						}
					}
					OutputStream outs=resp.getOutputStream();
					outs.write(response.getContent());
					outs.close();
				}
				catch(Exception e){
					e.printStackTrace();
				}
			}
			else{
				resp.setStatus(response.getResponseCode());
				resp.getWriter().close();
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
			try {
				resp.sendError(501);
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		} catch (IOException e) {
			e.printStackTrace();
			try {
				resp.sendError(501);
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
		return false;
	}
	
	class KeyValuePair{
		public String key;
		public String value;
		public KeyValuePair(String key,String value){
			this.key=key;
			this.value=value;
		}
	}
	
}
